/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.bff.slimserver.musicjukebox.ui.components;

import com.bff.bjj.ui.component.MusicList;
import com.bff.bjj.utils.Resources;
import com.bff.slimserver.music.MusicObjects;
import com.bff.slimserver.music.exceptions.PlaylistException;
import com.bff.slimserver.musicjukebox.lib.AlbumAllAlbum;
import com.bff.slimserver.musicjukebox.lib.JukeboxProperties;
import com.bff.slimserver.musicjukebox.lib.actions.PlaylistAddAlbumAction;
import com.bff.slimserver.musicjukebox.lib.actions.PlaylistInsertAlbumAction;
import com.bff.slimserver.musicjukebox.lib.actions.PlaylistLoadAlbumAction;
import com.bff.slimserver.musicjukebox.lib.actions.ViewAlbumAction;
import com.bff.slimserver.musicjukebox.ui.AlbumThumbnailDialog;
import com.bff.bjj.utils.Utils;
import com.bff.slimserver.utils.SlimComparator;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.AbstractAction;
import javax.swing.DefaultListModel;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import org.bff.slimserver.SlimDatabase;
import org.bff.slimserver.SlimPlaylist;
import org.bff.slimserver.exception.SlimConnectionException;
import org.bff.slimserver.musicobjects.SlimAlbum;
import org.bff.slimserver.musicobjects.SlimArtist;
import org.bff.slimserver.musicobjects.SlimGenre;

/**
 *
 * @author bfindeisen
 */
public class AlbumList extends MusicList implements MouseListener {

    private SlimDatabase database;
    private DefaultListModel albumListModel;
    private SlimPlaylist playlist;
    private JPopupMenu albumMenu;
    private JMenu albumViewOptionsMenu;
    private AlbumListCellRenderer albumListCellRenderer;
    private ListType type;
    private AlbumAllAlbum allAlbumYear;
    private AlbumAllAlbum allAlbumGenre;
    private AlbumAllAlbum allAlbumArtist;
    private boolean showArtistonDoubleClick;
    private boolean loading;
    private static SlimComparator slimComparator;

    public enum ListType {

        ARTIST, GENRE, YEAR
    }

    public AlbumList() {
        try {
            playlist = JukeboxProperties.getInstance().getPlaylist();
        } catch (PlaylistException ex) {
            Logger.getLogger(AlbumList.class.getName()).log(Level.SEVERE, null, ex);
        }
        slimComparator = new SlimComparator();
        albumListModel = new DefaultListModel();
        try {
            setDatabase(JukeboxProperties.getInstance().getDatabase());
        } catch (SlimConnectionException ex) {
            Logger.getLogger(AlbumList.class.getName()).log(Level.SEVERE, null, ex);
        }

        allAlbumYear = new AlbumAllAlbum(ListType.YEAR);
        allAlbumGenre = new AlbumAllAlbum(ListType.GENRE);
        allAlbumArtist = new AlbumAllAlbum(ListType.ARTIST);

        this.albumListCellRenderer = new AlbumListCellRenderer(getType());
        setCellRenderer(this.albumListCellRenderer);

        addMouseListener(this);

        albumViewOptionsMenu = new JMenu(Resources.getMessage(Resources.LABEL_KEY.ALBUM_VIEW_OPTIONS));
        albumViewOptionsMenu.add(new JMenuItem(new AbstractAction(Resources.getMessage(Resources.LABEL_KEY.ALBUM_VIEW_ART)) {

            @Override
            public void actionPerformed(ActionEvent e) {
                JukeboxProperties.getInstance().setAlbumListArt(true);
            }
        }));

        albumViewOptionsMenu.add(new JMenuItem(new AbstractAction(Resources.getMessage(Resources.LABEL_KEY.ALBUM_VIEW_TEXT)) {

            @Override
            public void actionPerformed(ActionEvent e) {
                JukeboxProperties.getInstance().setAlbumListArt(false);
            }
        }));

        this.showArtistonDoubleClick = true;
    }

    public void setType(ListType type) {
        this.type = type;
        getAlbumListCellRenderer().setType(type);
    }

    public ListType getType() {
        return type;
    }

    public void setArtist(SlimArtist artist) {
        setType(ListType.ARTIST);
        allAlbumArtist.setArtist(artist.getName());
        listAlbums(artist);
    }

    public void setYear(String year) {
        setType(ListType.YEAR);
        allAlbumYear.setYear(year);
        listAlbums(year);
    }

    public void setGenre(SlimGenre genre) {
        setType(ListType.GENRE);
        allAlbumGenre.setGenre(genre);
        listAlbums(genre);
    }

    public void setAlbums(Collection<SlimAlbum> albums) {
        try {
            albumListModel.clear();
            getAlbumListCellRenderer().clearPanels();
            for (SlimAlbum album : albums) {
                albumListModel.addElement(album);
            }

            setModel(albumListModel);
            setSelectedIndex(0);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void listAlbums(String year) {
        if (!isLoading()) {
            setLoading(true);
            List<SlimAlbum> albumList = null;
            try {
                albumListModel.clear();
                getAlbumListCellRenderer().clearPanels();
                albumListModel.addElement(allAlbumYear);
                albumList = new ArrayList<SlimAlbum>(getDatabase().listAlbumsForYear(year));

                Collections.sort(albumList, slimComparator);

                for (SlimAlbum album : albumList) {
                    albumListModel.addElement(album);
                }

                setModel(albumListModel);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                setLoading(false);
            }
        }
    }

    private void listAlbums(SlimArtist artist) {
        if (!isLoading()) {
            setLoading(true);
            List<SlimAlbum> albumList = null;
            try {
                albumListModel.clear();
                getAlbumListCellRenderer().clearPanels();
                albumListModel.addElement(allAlbumArtist);
                albumList = new ArrayList<SlimAlbum>(getDatabase().listAlbumsForArtist(artist));

                Collections.sort(albumList, slimComparator);

                for (SlimAlbum album : albumList) {
                    albumListModel.addElement(album);
                }

                setModel(albumListModel);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                setLoading(false);
            }
        }
    }

    private void listAlbums(SlimGenre genre) {
        if (!isLoading()) {
            setLoading(true);
            List<SlimAlbum> albumList = null;
            try {
                albumListModel.clear();
                getAlbumListCellRenderer().clearPanels();
                albumListModel.addElement(allAlbumGenre);
                albumList = new ArrayList<SlimAlbum>(getDatabase().listAlbumsForGenre(genre));

                Collections.sort(albumList, slimComparator);

                for (SlimAlbum album : albumList) {
                    albumListModel.addElement(album);
                }

                setModel(albumListModel);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                setLoading(false);
            }
        }
    }

    public void listAll() {
        List<SlimAlbum> albumList = null;
        try {
            albumListModel.clear();
            getAlbumListCellRenderer().clearPanels();
            albumList = new ArrayList<SlimAlbum>(MusicObjects.getAlbums());

            Collections.sort(albumList, slimComparator);

            for (SlimAlbum album : albumList) {
                albumListModel.addElement(album);
            }

            setModel(albumListModel);
            setSelectedIndex(0);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public SlimAlbum getSelectedAlbum() {
        return (SlimAlbum) getSelectedValue();
    }

    public SlimDatabase getDatabase() {
        return database;
    }

    public void setDatabase(SlimDatabase database) {
        this.database = database;
    }

    private void createAlbumPlayPopUp(MouseEvent e) {
        if (e.isPopupTrigger()) {
            setSelectedIndex(locationToIndex(e.getPoint()));
            SlimAlbum album = getSelectedAlbum();
            albumMenu = new JPopupMenu();
            albumMenu.add(new JMenuItem(new PlaylistAddAlbumAction(getPlaylist(), album)));
            albumMenu.add(new JMenuItem(new PlaylistInsertAlbumAction(getPlaylist(), album)));
            albumMenu.add(new JMenuItem(new PlaylistLoadAlbumAction(getPlaylist(), album)));
            albumMenu.add(new JMenuItem(new ViewAlbumAction(Utils.getParentComponent(this), album)));

            albumMenu.addSeparator();

            albumMenu.add(albumViewOptionsMenu);

            albumMenu.setVisible(true);
            albumMenu.show(e.getComponent(), e.getX(), e.getY());
        }
    }

    public SlimPlaylist getPlaylist() {
        return playlist;
    }

    public void setPlaylist(SlimPlaylist playlist) {
        this.playlist = playlist;
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        if (e.getClickCount() == 2) {
            if (isShowArtistonDoubleClick()) {
                SlimAlbum album = getSelectedAlbum();
                new AlbumThumbnailDialog(Utils.getParentComponent(this), album).setVisible(true);
            }
        } else {
            createAlbumPlayPopUp(e);
        }
    }

    @Override
    public void mousePressed(MouseEvent e) {
        createAlbumPlayPopUp(e);
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        createAlbumPlayPopUp(e);
    }

    @Override
    public void mouseEntered(MouseEvent e) {
        //throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void mouseExited(MouseEvent e) {
        //throw new UnsupportedOperationException("Not supported yet.");
    }

    /**
     * @return the albumListCellRenderer
     */
    public AlbumListCellRenderer getAlbumListCellRenderer() {
        return albumListCellRenderer;
    }

    /**
     * @param albumListCellRenderer the albumListCellRenderer to set
     */
    public void setAlbumListCellRenderer(AlbumListCellRenderer albumListCellRenderer) {
        this.albumListCellRenderer = albumListCellRenderer;
    }

    /**
     * @return the showArtistonDoubleClick
     */
    public boolean isShowArtistonDoubleClick() {
        return showArtistonDoubleClick;
    }

    /**
     * @param showArtistonDoubleClick the showArtistonDoubleClick to set
     */
    public void setShowArtistonDoubleClick(boolean showArtistonDoubleClick) {
        this.showArtistonDoubleClick = showArtistonDoubleClick;
    }

    /**
     * @return the loading
     */
    public boolean isLoading() {
        return loading;
    }

    /**
     * @param loading the loading to set
     */
    public void setLoading(boolean loading) {
        this.loading = loading;
    }

    public void clear() {
        albumListModel.clear();
    }
}
